package com.dhcc.crftool.uilts;

import com.dhcc.crftool.enums.ResultCodeEnum;
import com.dhcc.crftool.enums.ResultStatusEnum;
import lombok.Data;

import java.io.Serializable;
import java.net.ConnectException;
import java.sql.SQLException;

/**
 * 统一定义ResponseBody 返回结构
 * @author felix
 */
@Data
public class ResultModel implements Serializable {
    private static final long serialVersionUID = 1071681926787951549L;

    /**
     * 响应业务状态
     */
    private Integer status;

    /**
     * 业务响应码
     */
    private Integer code;

    /**
     *  响应消息
     */
    private String msg;

    /**
     * 响应中的数据
     */
    private Object data;

    /**
     * 是否请求成功
     */
    private boolean success;

    /**
     * 分页查询时有效
     */
    private long total;

    public static ResultModel ok() {
        return new ResultModel(ResultCodeEnum.SUCCESS, ResultStatusEnum.OK, ResultStatusEnum.OK.getMsg(), null, true);
    }

    public static ResultModel ok(Object data) {
        return new ResultModel(ResultCodeEnum.SUCCESS, ResultStatusEnum.OK, ResultStatusEnum.OK.getMsg(), data, true);
    }

    public static ResultModel ok(Object data, String msg) {
        return new ResultModel(ResultCodeEnum.SUCCESS, ResultStatusEnum.OK, msg, data, true);
    }

    public static ResultModel ok(Object data, String msg, Integer status) {
        ResultStatusEnum statusEnum = ResultStatusEnum.getByCode(status);
        return new ResultModel(ResultCodeEnum.SUCCESS, statusEnum, msg, data, true);
    }

    public static ResultModel ok(Object data, Integer status) {
        ResultStatusEnum statusEnum = ResultStatusEnum.getByCode(status);
        return new ResultModel(ResultCodeEnum.SUCCESS, statusEnum, statusEnum.getMsg(), data, true);
    }

    public static ResultModel fail() {
        return new ResultModel(ResultCodeEnum.ERROR, ResultStatusEnum.INTERNAL_SERVER_ERROR,
                ResultStatusEnum.INTERNAL_SERVER_ERROR.getMsg(), null, false);
    }
    public static ResultModel fail(Throwable throwable){
        return new ResultModel(throwable);
    }
    public static ResultModel fail(Object data, String msg) {
        return new ResultModel(ResultCodeEnum.ERROR, ResultStatusEnum.INTERNAL_SERVER_ERROR, msg, data, false);
    }

    public static ResultModel fail(Object data, String msg, Integer status) {
        ResultStatusEnum statusEnum = ResultStatusEnum.getByCode(status);
        return new ResultModel(ResultCodeEnum.ERROR, statusEnum, msg, data, false);
    }

    public static ResultModel fail(Object data, Integer status) {
        ResultStatusEnum statusEnum = ResultStatusEnum.getByCode(status);
        return new ResultModel(ResultCodeEnum.ERROR, statusEnum, statusEnum.getMsg(), data, false);
    }

    public static ResultModel pageOk(Object data, long total) {
        ResultModel model = new ResultModel(ResultCodeEnum.SUCCESS, ResultStatusEnum.OK, ResultStatusEnum.OK.getMsg(),
                data, true);
        model.setTotal(total);

        return model;
    }

    public static ResultModel format(ResultStatusEnum statusEnum) {
        boolean isSuccess = true;
        ResultCodeEnum codeEnum = ResultCodeEnum.SUCCESS;
        switch (statusEnum){
            case INVALID_REQUEST:
            case UNAUTHORIZED:
            case FORBIDDEN:
            case NOT_FOUND:
            case INTERNAL_SERVER_ERROR:
                codeEnum = ResultCodeEnum.ERROR;
                isSuccess = false;
                break;
            default:
                break;
        }

        return new ResultModel(codeEnum, statusEnum,
                statusEnum.getMsg(), null, isSuccess);
    }

    public static ResultModel format(ResultStatusEnum statusEnum, String msg, Object data){

        boolean isSuccess = true;
        ResultCodeEnum codeEnum = ResultCodeEnum.SUCCESS;
        switch (statusEnum){
            case INVALID_REQUEST:
            case UNAUTHORIZED:
            case FORBIDDEN:
            case NOT_FOUND:
            case INTERNAL_SERVER_ERROR:
                codeEnum = ResultCodeEnum.ERROR;
                isSuccess = false;
                break;
            default:
                break;
        }

        return new ResultModel(codeEnum, statusEnum,
                msg, data, isSuccess);
    }

    private ResultModel(ResultCodeEnum codeEnum, ResultStatusEnum statusEnum, String msg, Object data, boolean isSuccess) {
        this.status = statusEnum.getCode();
        this.code = codeEnum.getCode();
        this.msg = msg;
        this.data = data;
        this.success = isSuccess;
        this.total = 0;
    }

    public ResultModel(Throwable throwable){
        this.success = false;
        this.status = 500;
        if(throwable instanceof NullPointerException){
            this.code= 1001;
            this.msg="空指针："+throwable;
        }else if(throwable instanceof ClassCastException ){
            this.code= 1002;
            this.msg = "类型强制转换异常："+throwable;
        }else if(throwable instanceof ConnectException){
            this.code= 1003;
            this.msg ="链接失败："+throwable;
        }else if(throwable instanceof IllegalArgumentException ){
            this.code= 1004;
            this.msg ="传递非法参数异常："+throwable;
        }else if(throwable instanceof NumberFormatException){
            this.code= 1005;
            this.msg ="数字格式异常："+throwable;
        }else if(throwable instanceof IndexOutOfBoundsException){
            this.code= 1006;
            this.msg ="下标越界异常："+throwable;
        }else if(throwable instanceof SecurityException){
            this.code= 1007;
            this.msg ="安全异常："+throwable;
        }else if(throwable instanceof SQLException){
            this.code= 1008;
            this.msg ="数据库异常："+throwable;
        }else if(throwable instanceof ArithmeticException){
            this.code= 1009;
            this.msg ="算术运算异常："+throwable;
        }else if(throwable instanceof RuntimeException){
            this.code = 1010;
            this.msg ="运行时异常："+throwable;
        }else if(throwable instanceof Exception){
            this.code= 9999;
            this.msg ="未知异常"+throwable;
        }
    }
}